package cc.wanforme.fsync.entity;

import cc.wanforme.fsync.util.DateTimeTool;
import cc.wanforme.fsync.util.FileNameUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** 同步单个文件的信息 */
public class SyncMetaDto extends SyncMeta {

    /* server 的文件根路径，可以为 null。<br/>
     * 递归同步文件夹时才会用到。用于处理 rewritePath 重写文件路径。
     */
    private String sourceBase;

    // server 的文件根路径，可以为 null。
    private String targetBase;

    public SyncMetaDto() {}

    public static SyncMetaDto from(SyncMeta source, String sourceBase, String targetBase) {
        SyncMetaDto meta = new SyncMetaDto();
        BeanUtils.copyProperties(source, meta);
        meta.sourceBase = sourceBase;
        meta.targetBase = targetBase;
        return meta;
    }

    /** 简答检查重写路径是否合法，合法返回 null， 不合法返回原因 */
//    private static final Pattern rewritePattern = Pattern.compile("(\\{.+\\})?");
    private static final Pattern rewritePattern = Pattern.compile("\\{.[^}]+\\}");
    public static String checkRewritePath(String rewrite) {
        if(rewrite == null) {
            return null;
        }

        if(!rewrite.startsWith(":")) {
            return "必须以':'开头";
        }

        // 检查格式化时间
        Matcher matcher = rewritePattern.matcher(rewrite.trim());
        while(matcher.find()) {
            String str = matcher.group();
            if(str.equals("")){
                continue;
            }

//            System.out.println("str: " + str);
            String patternStr = str.substring(1, str.length()-1);
            if(patternStr.contains("?") || patternStr.contains(":")) {
                return "文件名不能包含 ?: 等字符。 '" + str + "'";
            }

            DateTimeFormatter formatter = DateTimeTool.getFormatter(patternStr);
            if(formatter == null) {
                return "无效格式： '" + str + "'";
            }
        }

        return null;
    }

    /** 获取经过 rewritePath 转换后的文件真实路径。<br/>
     * 仅适用于文件，不适用文件夹 */
    public String decodeRewritePath(LocalDateTime dateTime) {
        String rewritePath = getRewritePath();
        String target = getTarget();

        File file = new File(target);
//        String fileName = file.getName();
        // 如果手动设置了 targetBase，父路径就是 targetBase，没有就是文件的逻辑父路径
        // 有 targetBase, 文件夹递归同步， 没有 targetBase, 普通的单文件同步
        String parent = getTargetBase();
        parent = parent == null ? file.getParent() : parent;
        if(parent.endsWith("/") || parent.endsWith("\\")) {
            parent = parent.substring(0, parent.length()-1);
        }

        if(!StringUtils.hasText(rewritePath)) {
            return parent + target;
        }

        // 将名称和路径合并在一起  target-原来的子路径
//        String nameNoSuffix = FileNameUtil.getNameNoSuffix(fileName);
//        String suffix = FileNameUtil.getSuffix(fileName);
        String nameNoSuffix = FileNameUtil.getNameNoSuffix(target);
        if(nameNoSuffix.endsWith("/") || nameNoSuffix.endsWith("\\")) {
            nameNoSuffix = nameNoSuffix.substring(0, nameNoSuffix.length()-1);
        }
        String suffix = FileNameUtil.getSuffix(target);

        // 先替换时间
        StringBuffer sb = new StringBuffer();
        Matcher matcher = rewritePattern.matcher(rewritePath.trim());
        while(matcher.find()) {
            String str = matcher.group();
            if(str.equals("")){
                continue;
            }

//            System.out.println("str: " + str);
            String patternStr = str.substring(1, str.length()-1);
            DateTimeFormatter formatter = DateTimeTool.getFormatter(patternStr);
            if(formatter != null) {
                String time = formatter.format(dateTime);
                matcher.appendReplacement(sb, time);
            } else {
                matcher.appendReplacement(sb, str);
            }
        }
        matcher.appendTail(sb);

        // 再替换父路径和无后缀文件名
        String finalStr = sb.isEmpty() ? rewritePath : sb.toString();
        finalStr = parent + finalStr.substring(1) // finalStr.replace(":", parent)
                .replace("?", nameNoSuffix)
                + suffix;
        return finalStr;
    }

    public void setSourceBase(String sourceBase) {
        this.sourceBase = sourceBase;
    }

    public String getSourceBase() {
        return sourceBase;
    }

    public void setTargetBase(String targetBase) {
        this.targetBase = targetBase;
    }

    public String getTargetBase() {
        return targetBase;
    }

}
